﻿using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Kangaroo.Configuration;
using Kangaroo.Controls;
using Kangaroo.DAL;
using Kangaroo.Model;
using Kangaroo.Shell.Utils;

namespace Kangaroo.Shell
{
    partial class Main
    {
        #region Nested type: MapView

        private class MapView : BaseView
        {
            private readonly Dictionary<ChannelInfo, MapMarker> _markers =
                new Dictionary<ChannelInfo, MapMarker>();

            public MapView(Main mainWin)
                : base(mainWin)
            {
                SetMap();
                LoadChannelPositions();
                MainWin.picMap.Resize += picMap_Resize;
            }

            private void LoadChannelPositions()
            {
                try
                {
                    foreach(var channelPosition in Config.Instance.ChannelPositions)
                    {
                        var marker = new MapMarker(channelPosition.Channel, MainWin.picMap.Size,
                            FromPointOnMap(new Point(channelPosition.X, channelPosition.Y),
                                MainWin.picMap.ClientSize, MainWin.picMap.Image.Size));
                        MainWin.picMap.Controls.Add(marker);
                        _markers.Add(channelPosition.Channel, marker);
                    }
                }
                catch(ArgumentException)
                {
                    MessageBox.Show("配置文件错误：重复的检测装置位置设定");
                    throw;
                }
            }

            private void SetMap()
            {
                try
                {
                    MainWin.picMap.Image = Image.FromFile(Config.Instance.MapFile);
                }
                catch(FileNotFoundException ex)
                {
                    MessageBox.Show(string.Format(Resource.MapView_SetMap_CannotFindMapFile, Config.Instance.MapFile));
                    throw;
                }
                catch(Exception ex)
                {
                    MessageBox.Show(string.Format(Resource.MapView_SetMap_MapFileError, Config.Instance.MapFile));
                    throw;
                }
            }

            private void picMap_Resize(object sender, EventArgs e)
            {
                // 若是最小化则不予处理
                if(MainWin.WindowState == FormWindowState.Minimized)
                {
                    return;
                }

                // 更新所有Marker的位置
                foreach(var marker in _markers.Values)
                {
                    marker.UpdateParentSize(MainWin.picMap.ClientSize);
                }
            }

            public override void Refresh()
            {
                Data.Alarm.ListLastAlarmForEachChannelAsync().Then(
                    lastAlarmForEachChannel => MainWin.BeginInvoke((Action)delegate
                    {
                        try
                        {
                            MainWin.OnDataConnectionSuccess();
                            foreach (var alarmInfo in
                                lastAlarmForEachChannel.Where(a => _markers.ContainsKey(a.Channel)))
                            {
                                // 若报警发生在地图上所显示的位置，则刷新报警
                                RefreshMarker(alarmInfo);
                            }
                        }
                        catch (Exception ex)
                        {
                            MainWin.UIFailureHandler(ex);
                        }
                    }), MainWin.DataErrorHandler);
            }

            private void RefreshMarker(AlarmInfo alarmInfo)
            {
                _markers[alarmInfo.Channel].AlarmLevel = alarmInfo.AlarmLevel;
            }

            private static Point FromPointOnMap(
                Point pointOnMap, Size pictureSize, Size mapSize)
            {
                var x = (int)Math.Round(pointOnMap.X * 1.0 / mapSize.Width * pictureSize.Width);
                var y = (int)Math.Round(pointOnMap.Y * 1.0 / mapSize.Height * pictureSize.Height);
                return new Point(x, y);
            }

            public override void Activate()
            {
                MainWin.splitInfoChart.Hide();
                MainWin.picMap.Show();
                MainWin.picMap.Dock = DockStyle.Fill;

                UIHelper.DisableToolStripButtons(
                    MainWin.characteristicStripButton,
                    MainWin.historyStripButton,
                    MainWin.dataWindowToolStripButton,
                    MainWin.characteristicToolStripMenuItem,
                    MainWin.historyToolStripMenuItem,
                    MainWin.dataWindowToolStripMenuItem);
            }
        }

        #endregion
    }
}